import { getUniqueKey } from "@/utils"
import { ITask, ITransportTask, ITransportTaskList, TaskPriority, TaskStatus, TaskType } from "./types"


export default class TaskController {

    /**
     * 新增运输任务
     *
     * @param fromRoomName
     * @param targetRoomName
     * @param fromId
     * @param targetId
     * @param creepId
     * @param resType
     * @param amount
     * @returns
     */
    static addTransportTask(
        priority: TaskPriority,
        fromRoomName: string,
        targetRoomName: string,
        fromId: string,
        targetId: string,
        resType: ResourceConstant,
        amount: number
    ): number {
        const taskId = getUniqueKey()
        const transportTask: ITransportTask = {
            id: taskId,
            priority: priority,
            type: TaskType.TRANSPORT,
            fromRoomName: fromRoomName,
            targetRoomName: targetRoomName,
            fromId: fromId,
            targetId: targetId,
            resType: resType,
            amount: amount,
            status: TaskStatus.PENDING,
        }

        if (!TaskController.hasTask(transportTask)) {
            TaskController.addTask(transportTask)
            return taskId
        }
        // console.log('[addTransportTask] task already exist', transportTask.fromRoomName, transportTask.resType, transportTask.amount)
        return 0
    }

    static addTask(task: ITask): number {
        if (!Memory.tasks || !Memory.tasks[TaskType.TRANSPORT]) {
            Memory.tasks = {
                [TaskType.TRANSPORT]: {},
            }
        }

        switch (task.type) {
            case TaskType.TRANSPORT:
                Memory.tasks[task.type][task.id] = task as ITransportTask
                console.log(`[${(task as ITransportTask).fromRoomName}] addTransportTask ${task.id}`)
                break
        }

        return task.id
    }

    static hasTask(task: ITask): any {

        switch (task.type) {
            case TaskType.TRANSPORT:
                const newTask = task as ITransportTask
                const tasks = Memory.tasks[TaskType.TRANSPORT] as ITransportTaskList
                if (!tasks || Object.keys(tasks).length == 0) {
                    return false
                }
                if (newTask) {
                    const result = Object.values(tasks).filter(t =>
                        t.fromRoomName == newTask.fromRoomName &&
                        t.targetRoomName == newTask.targetRoomName &&
                        t.fromId == newTask.fromId &&
                        t.targetId == newTask.targetId &&
                        t.resType == newTask.resType
                    )
                    if (result.length > 0) {
                        return true
                    }
                }
                break
        }
        return false
    }

    static cleanTask(): any {
        const transportTasks = Object.keys(Memory.tasks[TaskType.TRANSPORT])
        for (const id in transportTasks) {
            if (Game.time - parseFloat(transportTasks[id]) > 1000) {
                TaskController.finishTask(TaskType.TRANSPORT, parseFloat(transportTasks[id]))
            }
        }

    }

    static getTransportTaskByFromId(fromId: string): ITransportTask | null {
        const task = TaskController.getTaskByFromId(TaskType.TRANSPORT, fromId) as ITransportTask
        if (task) {
            return task
        }
        return null
    }

    static getTaskByFromId(type: TaskType, fromId: string): ITask | null {
        if (Memory.tasks && Memory.tasks[type]) {
            const tasks = Memory.tasks[type] as ITransportTaskList
            if (!tasks || Object.keys(tasks).length == 0) {
                return null
            }
            const tasksFilter = Object.values(tasks).filter(t => {
                t.fromId == fromId &&
                    t.type == type
            })
            if (tasksFilter && tasksFilter[0]) {
                return tasksFilter[0]
            }
        }
        return null
    }

    static getTransportTaskById(id: number): ITransportTask | null {
        const task = TaskController.getTaskById(TaskType.TRANSPORT, id) as ITransportTask
        if (task) {
            return task
        }
        return null
    }

    static getTaskById(type: TaskType, id: number): ITask | null {
        if (Memory.tasks && Memory.tasks[type]) {
            if (id) {
                return Memory.tasks[type][id]
            }

            const tasks = Memory.tasks[type] as ITransportTaskList
            if (!tasks || Object.keys(tasks).length == 0) {
                return null
            }
            const tasksFilter = Object.values(tasks).filter(t => {
                t.id == id &&
                    t.type == type
            })
            if (tasksFilter && tasksFilter[0]) {
                return tasksFilter[0]
            }
        }
        return null
    }

    static getTransportTask(roomName: string): ITransportTask | null {
        const task = TaskController.getTask(roomName, TaskType.TRANSPORT) as ITransportTask
        if (task) {
            return task
        }
        return null
    }

    static getTask(roomName: string, type: TaskType): ITask | null {
        if (Memory.tasks && Memory.tasks[type]) {

            const tasks = Memory.tasks[type] as ITransportTaskList
            if (!tasks || Object.keys(tasks).length == 0) {
                return null
            }

            const sortedTasks = _.sortBy(Object.values(tasks), task => -task.priority)

            const tasksFilter = Object.values(sortedTasks).filter(t =>
                (
                    t.fromRoomName == roomName ||
                    t.targetRoomName == roomName
                ) &&
                t.status == TaskStatus.PENDING
            )
            if (tasksFilter && tasksFilter[0]) {
                return tasksFilter[0]
            }
        }
        return null
    }

    /**
     * 接任务
     * @param type
     * @param id
     * @returns
     */
    static acceptTask(type: TaskType, id: number): ITask | null {
        const task = TaskController.updateTask(type, id, TaskStatus.STARTED)
        if (task) {
            console.log(`[${(task as ITransportTask).fromRoomName}] acceptTask ${task.id}`)
            return task
        }
        return null
    }

    /**
     * 放弃任务
     * @param type
     * @param id
     * @returns
     */
    static abandonTask(type: TaskType, id: number): ITask | null {
        const task = TaskController.updateTask(type, id, TaskStatus.PENDING)
        if (task) {
            console.log(`[${(task as ITransportTask).fromRoomName}] abandonTask ${task.id}`)
            return task
        }
        return null
    }

    static updateTask(type: TaskType, id: number, status: TaskStatus): ITask | null {
        if (Memory.tasks && Memory.tasks[type] && Memory.tasks[type][id]) {
            const task = Memory.tasks[type][id]
            if (task) {
                task.status = status
                Memory.tasks[type][id] = task
                console.log(`[${(task as ITransportTask).fromRoomName}] updateTask ${task.id}`)
                return task
            }
        }
        return null
    }

    /**
     * 完成任务
     * @param type
     * @param id
     * @returns
     */
    static finishTask(type: TaskType, id: number): void {
        const task = Memory.tasks[type][id]
        if (task) {
            console.log(`[${(task as ITransportTask).fromRoomName}] finishTask ${task.id}`)
        }
        else {
            console.log(`[_] finishTask ${task.id}`)
        }
        delete Memory.tasks[type][id]
    }
}
